package com.sbl.bajw.common;

import java.util.Map;
import java.util.Properties;

import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.RowBounds;

@Intercepts({@org.apache.ibatis.plugin.Signature(type=org.apache.ibatis.executor.statement.StatementHandler.class, method="prepare", args={java.sql.Connection.class})})
public class PageInterceptor implements Interceptor {

	@Override
	public Object intercept(Invocation ivk) throws Throwable {
		
		if ((ivk.getTarget() instanceof RoutingStatementHandler)) {
		      RoutingStatementHandler statementHandler = (RoutingStatementHandler)ivk.getTarget();
		      MetaObject metaStatementHandler = MetaObject.forObject(statementHandler);
		      Object parameter = statementHandler.getParameterHandler().getParameterObject();
		      BoundSql boundSql = statementHandler.getBoundSql();
		      String sql = boundSql.getSql();

		      if (parameter != null && parameter instanceof Map) {
		          @SuppressWarnings("rawtypes")
				Object pageParameter = ((Map)parameter).get("pageParameter");
		          if(pageParameter instanceof Page){
		        	  Page page = (Page)pageParameter;
		        	  String orderString = page.getOrderString();
		        	  int offset = page.getPageSize() * (page.getPageIndex()-1);
		        	  sql = getLimitString(sql, offset, page.getPageSize());
		        	  if(orderString != null && !orderString.trim().equals("")){
		        		  sql += " ORDER BY "+orderString;
		        	  }
		        	  ReflectUtils.setValueByFieldName(boundSql, "sql", sql);
		          }
		      }
		      metaStatementHandler.setValue("delegate.rowBounds.offset",RowBounds.NO_ROW_OFFSET);  
		      metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT); 
		}
		
		return ivk.proceed();
	}

	@Override
	public Object plugin(Object arg0) {
		return Plugin.wrap(arg0, this);
	}

	@Override
	public void setProperties(Properties arg0) {
		// TODO Auto-generated method stub

	}
	
	 public String getLimitString(String sql, int offset, int limit)
	  {
	    sql = sql.trim();

	    StringBuffer pagingSelect = new StringBuffer(sql.length() + 100);
	    if (offset > 0)
	      pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
	    else {
	      pagingSelect.append("select * from ( ");
	    }
	    pagingSelect.append(sql);
	    if (offset > 0)
	      pagingSelect.append(" ) row_ ) where rownum_ <= " + (offset + limit) + " and rownum_ > " + offset);
	    else {
	      pagingSelect.append(" ) where rownum <= " + limit);
	    }

	    return pagingSelect.toString();
	  }

}
